using System;
using System.Linq;
using System.Collections.Generic;
using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace ReactiveLang
{
    [TestClass]
    public class ReactiveLangTestClassBase
    {
        List<ReactiveHandle> _handles;
        TestSyncContext _syncCtx;
        SynchronizationContext _origSyncCtx;
        public ReactiveHost Host { get; private set; }

        [TestInitialize]
        public void InitializeTest()
        {
            _origSyncCtx = SynchronizationContext.Current;
            _syncCtx = new TestSyncContext();
            SynchronizationContext.SetSynchronizationContext(_syncCtx);

            _handles = new List<ReactiveHandle>();
            Host = new ReactiveHost();
        }
        [TestCleanup]
        public void CleanupTest()
        {
            _handles = null;
            Host.Dispose();
            Host = null;
            SynchronizationContext.SetSynchronizationContext(_origSyncCtx);
        }

        protected ReactiveHandle Run(params IStatement<Unit>[] stmts)
        {
            var call = Host.Add(Statement.Block<Unit>(stmts));
            _handles.Add(call);
            return call;
        }
        protected void Resume()
        {
            foreach (var m in _handles)
                m.Enabled = true;
        }
        protected void Suspend()
        {
            foreach (var m in _handles)
            {
                m.Enabled = false;
            }
        }

        #region Factory methods
        protected IStatement<Unit> Assign<T>(IAssignableExpression<T> target, IExpression<T> value)
        {
            return Expression.Assign<T>(target, value).AsStatement<Unit, T>();
        }
        protected IStatement<Unit> If(IExpression<bool> test, IStatement<Unit> @true, IStatement<Unit> @false = null)
        {
            return Statement.If<Unit>(test, @true, @false);
        }
        #endregion
    }
}